package cmd

import (
	"Ethnic_Sink/properties"
	"Ethnic_Sink/routings"
	"Ethnic_Sink/util"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/memstore"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"net/http"
	"strconv"
)

type users struct {
	Uid      int    `json:"Uid"`
	Name     string `json:"Name"`
	Password string `json:"Password"`
	Imghead  string `json:"Imghead"`
}

type ethics struct {
	Id      int
	Name    string
	Coth    string
	History string
	Address string
}

var (
	DB      *gorm.DB
	redisDb *redis.Client
)

func InitDB() (*gorm.DB, error) {
	dsn := properties.Dsn
	var err error
	DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return nil, err
	}
	return DB, nil
}

func GetDB() *gorm.DB {
	return DB
}

func GetRedisDB() *redis.Client {
	return redisDb
}

func InitClient() (err error) {
	redisDb = redis.NewClient(&redis.Options{
		Addr:     "192.168.140.135:6379", // redis地址
		Password: "123456",               // redis密码，没有则留空
		DB:       0,                      // 默认数据库，默认是0
	})

	//通过 *redis.Client.Ping() 来检查是否成功连接到了redis服务器
	_, err = redisDb.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

func Getmax(DB *gorm.DB, name string, tabname string) (int, error) {
	var id int
	var err error
	if err1 := DB.Raw("SELECT MAX(" + name + ") FROM " + tabname).Scan(&id).Error; err != nil {
		err = err1
	}
	return id, err
}

func Excute() {
	r := gin.Default()
	store := memstore.NewStore([]byte("secret"))
	//session
	r.Use(sessions.Sessions("mysession", store))
	//使用解决跨域中间件
	r.Use(routings.Core())
	//GORM
	_, err := InitDB()
	if err != nil {
		panic(err)
		return
	}
	DB := GetDB()
	//redis
	err1 := InitClient()
	if err1 != nil {
		panic(err)
		return
	}
	redisDb := GetRedisDB()
	//路由组
	eGroup := r.Group("/ethnic")
	{
		//TODO login 登录
		eGroup.POST("/login", func(context *gin.Context) {
			id := context.PostForm("id")
			password := context.PostForm("password")
			var use users
			if err := DB.Where("uid=?", id).Find(&use).Error; err != nil {
				context.AbortWithError(http.StatusOK, err)
				return
			}
			pass_ := util.AesDecrypt(use.Password, util.Getkey())
			id_, err := strconv.Atoi(id)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"err": err.Error(),
				})
				return
			}
			if id_ != use.Uid || password != pass_ {
				context.JSON(http.StatusOK, gin.H{
					"err": "账号或密码错误",
				})
				return
			}
			name := use.Name
			token, err := util.GenerateToken(util.Getscret(), password, use.Uid, name, 4500)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"err": err.Error(),
				})
				return
			}
			session := sessions.Default(context)
			session.Set("token", token)
			session.Save()
			context.JSON(http.StatusOK, gin.H{
				"title": "OK",
				"massage": gin.H{
					"token":   token,
					"name":    name,
					"imghead": use.Imghead,
				},
			})
		})

		//TODO 验证 token,session
		eGroup.GET("/token", func(context *gin.Context) {
			session := sessions.Default(context)
			tokens := session.Get("token")
			token := fmt.Sprintf("%v", tokens)
			clims, err := util.ParseToken(util.Getscret(), token)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"askData": gin.H{
						"prompt":       "ERROR1",
						"defeatReason": err.Error(),
					},
				})
				return
			}
			context.JSON(http.StatusOK, gin.H{
				"token": clims["pass"],
			})
		})

		//TODO 注册
		eGroup.POST("/sign", func(context *gin.Context) {
			id := context.PostForm("id")
			pass := context.PostForm("password")
			name := context.PostForm("name")
			imagehead := "https://tse4-mm.cn.bing.net/th/id/OIP-C.t-PmW8lejRlEkxcxxD5StAAAAA"
			id_, err := strconv.Atoi(id)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"err": err.Error(),
				})
				return
			}
			password := util.AesEncrypt(pass, util.Getkey())
			var users = users{Uid: id_, Name: name, Password: password, Imghead: imagehead}
			if err := DB.Create(&users).Error; err != nil {
				context.AbortWithError(http.StatusOK, err)
				return
			}
			context.JSON(http.StatusOK, gin.H{
				"title": "OK",
			})
		})

		//TODO 修改密码
		eGroup.PUT("/revise", func(context *gin.Context) {
			session := sessions.Default(context)
			tokens := session.Get("token")
			token := fmt.Sprintf("%v", tokens)
			clims, err := util.ParseToken(util.Getscret(), token)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"askData": gin.H{
						"prompt":       "ERROR1",
						"defeatReason": err.Error(),
					},
				})
				return
			}
			uid := clims["uid"]
			pass := context.PostForm("password")
			pass_ := util.AesEncrypt(pass, util.Getkey())
			var use users
			if err := DB.Exec("update users set password=? where uid=?", pass_, uid).Error; err != nil {
				context.AbortWithError(http.StatusOK, err)
				return
			}
			if err := DB.Where("uid=?", uid).Find(&use).Error; err != nil {
				context.AbortWithError(http.StatusOK, err)
				return
			}
			token_, err := util.GenerateToken(util.Getscret(), pass, use.Uid, use.Name, 4500)
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"err": err.Error(),
				})
				return
			}
			session.Delete("token")
			session.Set("token", token_)
			session.Save()
			context.JSON(http.StatusOK, gin.H{
				"title": gin.H{
					"mas":   "OK",
					"error": "NULL",
				},
			})
		})

		//TODO 修改头像、昵称等

		//TODO 用户注销
		eGroup.DELETE("/delete/:id", func(context *gin.Context) {
			id, ok := context.Params.Get("id")
			if !ok {
				context.JSON(http.StatusOK, gin.H{
					"prompt": "无效的ID",
				})
				return
			}
			if err := DB.Exec("delete from users where uid=?", id).Error; err != nil {
				context.JSON(http.StatusOK, gin.H{
					"prompt": err.Error(),
				})
				return
			}
			context.JSON(http.StatusOK, gin.H{
				"msg": "OK",
			})
		})

		//TODO 传入民族信息
		eGroup.POST("/addethnic", func(context *gin.Context) {
			name := context.PostForm("name")
			history := context.PostForm("history")
			state := context.PostForm("state")
			festival := context.PostFormArray("festival")
			coth := context.PostForm("coth")
			photos := context.PostFormArray("photos")
			id, _ := Getmax(DB, "id", "ethics")
			id++
			var ethicss = ethics{Name: name, History: history, Address: state, Coth: coth, Id: id}
			if err := DB.Create(ethicss).Error; err != nil {
				context.JSON(http.StatusOK, gin.H{
					"title":   "err",
					"massage": err,
				})
				return
			}
			for i := 0; i < len(festival); i++ {
				err1 := redisDb.LPush(name+"节日", festival[i]).Err()
				if err1 != nil {
					context.JSON(http.StatusOK, gin.H{
						"title":   "err",
						"massage": err1,
					})
					return
				}
			}
			for i := 0; i < len(photos); i++ {
				err1 := redisDb.LPush(name+"图片", photos[i]).Err()
				if err1 != nil {
					context.JSON(http.StatusOK, gin.H{
						"title":   "err",
						"massage": err1,
					})
					return
				}
			}
			context.JSON(http.StatusOK, gin.H{
				"title": "OK",
			})
		})

		//TODO 展示民族库信息
		eGroup.GET("/ethnics/:name", func(context *gin.Context) {
			name, ok := context.Params.Get("name")
			if !ok {
				context.JSON(http.StatusOK, gin.H{
					"titke":   "error",
					"massage": "无效的民族",
				})
				return
			}
			var ethics ethics
			if err := DB.Where("name=?", name).Find(&ethics).Error; err != nil {
				context.JSON(http.StatusOK, gin.H{
					"title":   "ERROR",
					"massage": err,
				})
				return
			}
			values, err := redisDb.LRange(name+"节日", 0, -1).Result()
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"title":   "ERROR",
					"massage": err,
				})
				return
			}
			val1, err := redisDb.LRange(name+"图片", 0, -1).Result()
			if err != nil {
				context.JSON(http.StatusOK, gin.H{
					"title":   "ERROR",
					"massage": err,
				})
				return
			}
			context.JSON(http.StatusOK, gin.H{
				"title": "OK",
				"Result": gin.H{
					"text":     ethics,
					"festival": values,
					"photos":   val1,
				},
			})
		})

		//TODO 下一个业务
	}
	//TODO 更改端口
	r.Run()
}
